package util;

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import mill.*;
import mill.measurePoints.AirTemperature;
import mill.measurePoints.MeasurePoint;
import mill.measurePoints.WindDirection;
import mill.measurePoints.Windspeed;

public class Logger extends Thread implements Serializable
{
	public static Logger Instance = new Logger();
	
	private List<MillLog> l_logs = new ArrayList<MillLog>();
	private List<MillPark> l_parks = new ArrayList<MillPark>(); 
	private int m_numberOfEntries = 10000;
	private int m_timeBetweenEntries = 5;
	private DatabaseManager dbManager = DatabaseManager.Instance;
	
	private Logger()
	{
		//System.out.println("Logger started, will log data from all mills every " + m_timeBetweenEntries + " sec...");
	}
	
	public synchronized List<MillPark> get_parks() {
		return l_parks;
	}

	public synchronized void set_parks(List<MillPark> l_parks) {
		this.l_parks = l_parks;
	}

	public synchronized int getM_numberOfEntries() {
		return m_numberOfEntries;
	}

	public synchronized void setM_numberOfEntries(int ofEntries) {
		m_numberOfEntries = ofEntries;
	}

	public synchronized int getM_timeBetweenEntries() {
		return m_timeBetweenEntries;
	}

	public synchronized void setM_timeBetweenEntries(int betweenEntries) {
		m_timeBetweenEntries = betweenEntries;
	}

	// Implement the run() method for the thread
	public synchronized void run()
	{
		while(true)
		{	
			
			if(l_parks != null && l_parks.size() > 0 )
			{
			do
			{
				//System.out.println("t: " + m_timeBetweenEntries + " n:" + m_numberOfEntries);
				
				
				sleep(m_timeBetweenEntries);
				for (MillPark mp : l_parks) 
				{
					for (IMill mill : mp.getMills()) 
					{
						MillLog ml = new MillLog();
						ml.setTimeStamp(new java.sql.Timestamp(Calendar.getInstance().getTime().getTime()));
						ml.setSerialNumber(mill.getSerialNumber());
						ml.setPowerOutput(mill.getPowerOutput());

						for(MeasurePoint measurep : mill.getMeasurePoints())
						{
							if(measurep instanceof AirTemperature)
							{
								ml.setAirTemperature(((AirTemperature) measurep).get_measuredValue());
							}
							if(measurep instanceof WindDirection)
							{
								ml.setWindDirection(((WindDirection) measurep).get_windDirection());
							}
							if(measurep instanceof Windspeed)
							{
								ml.setWindSpeed(((Windspeed) measurep).get_windspeed());
							}
						}
						l_logs.add(ml);
					}
				} 
				//System.out.println("mill data collected: " + l_logs.size());
			}while(l_logs.size() < m_numberOfEntries);
			System.out.println("Max number of logs reached, array is serialized and cleared.");
			//Serialize list into a file and clear list.
			// Create file output stream.
			try {
				// Create file output stream.
				LogConfiguration logConf = new LogConfiguration(m_numberOfEntries, m_timeBetweenEntries);
				
				java.util.Date today = Calendar.getInstance().getTime();
				logConf.set_created(today);
				logConf.set_numberOfEntries(l_logs.size());
				String filename = "millData_" + today.toString() + ".log";
				filename = filename.replaceAll("CET ", "");
				filename = filename.replaceAll("Mon |Tue |Wed |Thu |Fri |Sat |Sun ", "");
				filename = filename.replace(':', '_');

				logConf.set_filename(filename);
				
				FileOutputStream fstream = new FileOutputStream("Log/"+filename);

				try {
					// Create object output stream.
					ObjectOutputStream ostream = new ObjectOutputStream(fstream);

					try {
						// Write object.
						ostream.writeObject(l_logs);
						ostream.flush();
						
						
						
					} finally {
						// Close object stream.
						ostream.close();
					}
				} finally {
					// Close file stream.
					fstream.close();
					
					try {
						dbManager.insert(logConf);
						
					} catch (Exception e) {
						// TODO: handle exception
						System.out.println(e.toString());
					}

				}
			} catch(Exception ex) {
				System.out.println(ex);
			}
			l_logs.clear();
			
			}
			else
				sleep(m_timeBetweenEntries);
		}
	}

	public List<MillLog> getMillLogs()
	{
		return(l_logs);
	}
	private void sleep(int sec){
		try {Thread.sleep(sec * 1000);} catch (Exception e){}
		
	}
}